1use super::entries::HeapEntry;
2use super::types::{HeapMetrics, HeapStats};
3use crate::vm::bytecode::Bytecode;
4use crate::vm::handle::HeapHandleId;
5use crate::vm::types::{ArgIndex, ArraySize, LocalIndex};
6use crate::vm::value::Value;
7use std::collections::HashMap;
8
9pub trait HeapAllocator {
10 fn allocate(&mut self, entry: HeapEntry) -> HeapHandleId;
11 fn deallocate(&mut self, handle: HeapHandleId) -> bool;
12 fn get(&self, handle: HeapHandleId) -> Option<&HeapEntry>;
13 fn get_mut(&mut self, handle: HeapHandleId) -> Option<&mut HeapEntry>;
14 fn get_entries(&self) -> &HashMap<HeapHandleId, HeapEntry>;
15 fn get_entries_mut(&mut self) -> &mut HashMap<HeapHandleId, HeapEntry>;
16 fn size(&self) -> usize;
17 fn is_empty(&self) -> bool;
18 fn clear(&mut self);
19 fn get_metrics(&self) -> &HeapMetrics;
20}
21
22pub trait GarbageCollector {
23 fn collect_garbage(
24 &mut self,
25 entries: &mut HashMap<HeapHandleId, HeapEntry>,
26 roots: &[HeapHandleId],
27 ) -> usize;
28 fn get_collection_stats(&self) -> (usize, u32, u32);
29}
30
31pub trait HeapManager {
32 fn get(&self, handle: HeapHandleId) -> Option<&HeapEntry>;
33 fn get_mut(&mut self, handle: HeapHandleId) -> Option<&mut HeapEntry>;
34 fn set_object_property(&mut self, handle: HeapHandleId, key: String, value: Value);
35 fn get_object_property(&self, handle: HeapHandleId, key: &str) -> Option<&Value>;
36 fn push_array_element(&mut self, handle: HeapHandleId, value: Value);
37 fn get_array_element(&self, handle: HeapHandleId, idx: ArraySize) -> Option<&Value>;
38 fn set_array_element(&mut self, handle: HeapHandleId, idx: ArraySize, value: Value);
39 fn remove_object_property(&mut self, handle: HeapHandleId, key: &str);
40 fn has_object_property(&self, handle: HeapHandleId, key: &str) -> bool;
41 fn size(&self) -> usize;
42 fn is_empty(&self) -> bool;
43 fn clear(&mut self);
44 fn get_stats(&self) -> HeapStats;
45 fn get_metrics(&self) -> &HeapMetrics;
46 fn collect_garbage(&mut self, roots: &[HeapHandleId]) -> usize;
47}
48
49pub trait HeapOperations {
50 fn alloc_object(&mut self) -> HeapHandleId;
51 fn alloc_array(&mut self) -> HeapHandleId;
52 fn alloc_function(
53 &mut self,
54 bytecode: Bytecode,
55 arg_count: ArgIndex,
56 local_count: LocalIndex,
57 ) -> HeapHandleId;
58 fn alloc_string(&mut self, value: String) -> HeapHandleId;
59}
60
61pub struct Heap {
62 allocator: Box<dyn HeapAllocator>,
63 gc: Box<dyn GarbageCollector>,
64 stats: HeapStats,
65 metrics: HeapMetrics,
66}
67
68impl Clone for Heap {
69 fn clone(&self) -> Self {
70 Self {
71 allocator: Box::new(super::allocation::HeapAllocatorImpl::new()),
72 gc: Box::new(super::garbage_collection::GarbageCollectorImpl::new()),
73 stats: self.stats.clone(),
74 metrics: self.metrics.clone(),
75 }
76 }
77}
78
79impl Heap {
80 pub fn new() -> Self {
81 Self {
82 allocator: Box::new(super::allocation::HeapAllocatorImpl::new()),
83 gc: Box::new(super::garbage_collection::GarbageCollectorImpl::new()),
84 stats: HeapStats::new(),
85 metrics: HeapMetrics::new(),
86 }
87 }
88
89 pub fn with_capacity(capacity: usize) -> Self {
90 Self {
91 allocator: Box::new(super::allocation::HeapAllocatorImpl::with_capacity(
92 capacity,
93 )),
94 gc: Box::new(super::garbage_collection::GarbageCollectorImpl::new()),
95 stats: HeapStats::new(),
96 metrics: HeapMetrics::new(),
97 }
98 }
99
100 pub fn alloc_object(&mut self) -> HeapHandleId {
102 let handle = self.allocator.allocate(HeapEntry::Object(HashMap::new()));
103 self.metrics.record_allocation();
104 self.update_stats();
105 handle
106 }
107
108 pub fn alloc_array(&mut self) -> HeapHandleId {
109 let handle = self.allocator.allocate(HeapEntry::Array(Vec::new()));
110 self.metrics.record_allocation();
111 self.update_stats();
112 handle
113 }
114
115 pub fn alloc_function(
116 &mut self,
117 bytecode: Bytecode,
118 arg_count: ArgIndex,
119 local_count: LocalIndex,
120 ) -> HeapHandleId {
121 let handle = self.allocator.allocate(HeapEntry::Function {
122 bytecode,
123 arg_count,
124 local_count,
125 closure_vars: HashMap::new(),
126 });
127 self.metrics.record_allocation();
128 self.update_stats();
129 handle
130 }
131
132 pub fn alloc_string(&mut self, value: String) -> HeapHandleId {
133 let handle = self.allocator.allocate(HeapEntry::String(value));
134 self.metrics.record_allocation();
135 self.update_stats();
136 handle
137 }
138
139 pub fn get(&self, handle: HeapHandleId) -> Option<&HeapEntry> {
141 self.allocator.get(handle)
142 }
143
144 pub fn get_mut(&mut self, handle: HeapHandleId) -> Option<&mut HeapEntry> {
145 self.allocator.get_mut(handle)
146 }
147
148 pub fn get_object_property(&self, handle: HeapHandleId, key: &str) -> Option<&Value> {
149 if let Some(HeapEntry::Object(obj)) = self.allocator.get(handle) {
150 obj.get(key)
151 } else {
152 None
153 }
154 }
155
156 pub fn set_object_property(&mut self, handle: HeapHandleId, key: String, value: Value) {
157 if let Some(HeapEntry::Object(obj)) = self.allocator.get_mut(handle) {
158 obj.insert(key, value);
159 }
160 }
161
162 pub fn set_array_element(&mut self, handle: HeapHandleId, idx: ArraySize, value: Value) {
163 if let Some(HeapEntry::Array(arr)) = self.allocator.get_mut(handle) {
164 let index = idx.as_usize();
165 if index < arr.len() {
166 arr[index] = value;
167 } else {
168 arr.resize(index + 1, Value::Undefined);
169 arr[index] = value;
170 }
171 }
172 }
173
174 fn update_stats(&mut self) {
175 let entries = self.allocator.get_entries();
176 let mut object_count = 0;
177 let mut array_count = 0;
178 let mut function_count = 0;
179 let mut string_count = 0;
180 let mut memory_usage = 0;
181
182 for entry in entries.values() {
183 match entry {
184 HeapEntry::Object(_) => object_count += 1,
185 HeapEntry::Array(_) => array_count += 1,
186 HeapEntry::Function { .. } => function_count += 1,
187 HeapEntry::String(_) => string_count += 1,
188 }
189 memory_usage += entry.memory_usage();
190 }
191
192 self.stats
193 .update_counts(object_count, array_count, function_count, string_count);
194 self.stats.set_memory_usage(memory_usage);
195 }
196}
197
198impl HeapManager for Heap {
199 fn get(&self, handle: HeapHandleId) -> Option<&HeapEntry> {
200 self.allocator.get(handle)
201 }
202
203 fn get_mut(&mut self, handle: HeapHandleId) -> Option<&mut HeapEntry> {
204 self.allocator.get_mut(handle)
205 }
206
207 fn set_object_property(&mut self, handle: HeapHandleId, key: String, value: Value) {
208 if let Some(HeapEntry::Object(obj)) = self.allocator.get_mut(handle) {
209 obj.insert(key, value);
210 }
211 }
212
213 fn get_object_property(&self, handle: HeapHandleId, key: &str) -> Option<&Value> {
214 if let Some(HeapEntry::Object(obj)) = self.allocator.get(handle) {
215 obj.get(key)
216 } else {
217 None
218 }
219 }
220
221 fn push_array_element(&mut self, handle: HeapHandleId, value: Value) {
222 if let Some(HeapEntry::Array(arr)) = self.allocator.get_mut(handle) {
223 arr.push(value);
224 }
225 }
226
227 fn get_array_element(&self, handle: HeapHandleId, idx: ArraySize) -> Option<&Value> {
228 if let Some(HeapEntry::Array(arr)) = self.allocator.get(handle) {
229 arr.get(idx.as_usize())
230 } else {
231 None
232 }
233 }
234
235 fn set_array_element(&mut self, handle: HeapHandleId, idx: ArraySize, value: Value) {
236 if let Some(HeapEntry::Array(arr)) = self.allocator.get_mut(handle) {
237 let index = idx.as_usize();
238 if index < arr.len() {
239 arr[index] = value;
240 } else {
241 arr.resize(index + 1, Value::Undefined);
242 arr[index] = value;
243 }
244 }
245 }
246
247 fn remove_object_property(&mut self, handle: HeapHandleId, key: &str) {
248 if let Some(HeapEntry::Object(obj)) = self.allocator.get_mut(handle) {
249 obj.remove(key);
250 }
251 }
252
253 fn has_object_property(&self, handle: HeapHandleId, key: &str) -> bool {
254 if let Some(HeapEntry::Object(obj)) = self.allocator.get(handle) {
255 obj.contains_key(key)
256 } else {
257 false
258 }
259 }
260
261 fn size(&self) -> usize {
262 self.allocator.size()
263 }
264
265 fn is_empty(&self) -> bool {
266 self.allocator.is_empty()
267 }
268
269 fn clear(&mut self) {
270 self.allocator.clear();
271 }
272
273 fn get_stats(&self) -> HeapStats {
274 self.stats.clone()
275 }
276
277 fn get_metrics(&self) -> &HeapMetrics {
278 &self.metrics
279 }
280
281 fn collect_garbage(&mut self, roots: &[HeapHandleId]) -> usize {
282 let entries = self.allocator.get_entries_mut();
283 let collected = self.gc.collect_garbage(entries, roots);
284 self.metrics.record_gc_cycle(std::time::Duration::ZERO);
285 collected
286 }
287}
288
289impl HeapOperations for Heap {
290 fn alloc_object(&mut self) -> HeapHandleId {
291 self.alloc_object()
292 }
293
294 fn alloc_array(&mut self) -> HeapHandleId {
295 self.alloc_array()
296 }
297
298 fn alloc_function(
299 &mut self,
300 bytecode: Bytecode,
301 arg_count: ArgIndex,
302 local_count: LocalIndex,
303 ) -> HeapHandleId {
304 self.alloc_function(bytecode, arg_count, local_count)
305 }
306
307 fn alloc_string(&mut self, value: String) -> HeapHandleId {
308 self.alloc_string(value)
309 }
310}
311
312impl Default for Heap {
313 fn default() -> Self {
314 Self::new()
315 }
316}